//
//  AppDelegate.swift
//  PMCPatient
//
//  Created by PMC on 2023/5/5.
//

import UIKit
@_exported import YSGFramework
@_exported import YSGOC
import HandyJSON
import PushKit

let updateUrl = "https://apps.apple.com/us/app/和平国际医院/id6448246991"

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    var ysxLoginModel = ReceiveModel()
    
    
    class func share() -> AppDelegate? {
        return UIApplication.shared.delegate as? AppDelegate
    }
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        initUIConfigure()
        initDelegate()
        
        MeetingManager.create()
 
        AMapServices.shared().apiKey = mapAppKey
        registerWeChat()
        setupUMPush(launchOptions)
        setupKeyboardManager()
        setRootVc()
        
        UIButton.initializeMethod()
        
        requestAuthorizations()
        
        alertUpdateTip()
        hookTest()
        
        return true
    }
    
    var rootVc: UIViewController {
        return window?.rootViewController ?? UIViewController()
    }
    
    public func setRootVc() {
        window = UIWindow(frame: UIScreen.main.bounds)
        let mainVc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "mainVcId") as! MainViewController
        window?.rootViewController = mainVc
        window?.makeKeyAndVisible()
    }
    
    private func setupKeyboardManager() {
        let manager = IQKeyboardManager.shared
        manager.enable = true
        manager.shouldResignOnTouchOutside = true
        manager.toolbarDoneBarButtonItemText = "确定"
    }
    
    /// 授权
    private func requestAuthorizations() {
        AVAudioSession.authorizeToMicrophone { granted in
            if !granted {
                AlertTool.showAlert(self.rootVc,
                                    message: "需要访问您的麦克风\n请启用麦克风-设置-隐私-麦克风",
                                    sureTitle: "去打开",
                                    cancelTitle: "取消",
                                    type: .double,
                                    sureHandler: { (action) in
                    SettingTools.openAppSetting()
                })
            }
        }
    }
    
    /// 弹出更新提示
    public func alertUpdateTip() {
//        let updateURL = URL(string: updateUrl)!
//        YSGAppManager.getAppStoreAppVersion { (version, forceUpdate, code) in
//            switch code {
//            case .failure: break
//            case .success:
//                if forceUpdate {
//                    AlertTool.showAlert(self.rootVc, title: "您有新版本(v\(version))更新", sureTitle: "去更新", sureHandler: { _ in
//                        if UIApplication.shared.canOpenURL(updateURL) {
//                            UIApplication.shared.open(updateURL, options: [:], completionHandler: nil)
//                        }
//                    })
//                } else {
//                    AlertTool.showAlert(self.rootVc, title: "您有新版本(v\(version))更新", sureTitle: "现在更新", cancelTitle: "取消", type: .double, sureHandler: { _ in
//                        if UIApplication.shared.canOpenURL(updateURL) {
//                            UIApplication.shared.open(updateURL, options: [:], completionHandler: nil)
//                        }
//                    }, cancelHandler: nil)
//                }
//            }
//        }
    }

}

extension AppDelegate {
    private func initUIConfigure() {
        if #available(iOS 15.0, *) {
            UITableView.appearance().sectionHeaderTopPadding = 0
        }
    }
    
    private func initDelegate() {
        HttpTool.shared.delegate = self
    }
    
    
    public class func logout(inSelf: Bool) {
        WebSocketManager.destroy()
        UserDefaults.removeUserInfo()
        MeetingManager.shared.manager?.logoutSDK()
        if inSelf {
            mainWindow.rootViewController = LoginViewController()
        } else {
            AlertTool.showAlert(mainWindow.rootViewController!,
                                message:"您的账号在其他地方登陆，请确定是本人操作？",
                                sureTitle: "我知道了",
                                sureHandler: { (_) in
                mainWindow.rootViewController = LoginViewController()
            })
        }
    }
}

extension AppDelegate {
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        
        return true
    }
}

extension AppDelegate: HttpToolDelegate {
    func logout(code: Int) {
        AppDelegate.logout(inSelf: false)
    }
}

extension AppDelegate {
    func hookTest() {
//        hookPrint()
//        hookNSLog()
    }
    
    func hookPrint() {
        typealias MyPrint = @convention(thin) (Any..., String, String) ->Void
        func myPrint(_ items: Any..., separator: String = " ", terminator: String = "\n") {
            
        }
        let myprint: MyPrint = myPrint
        let myPrintPointer = unsafeBitCast(myprint, to: UnsafeMutableRawPointer.self)
        var oldMethod: UnsafeMutableRawPointer?
        
        FishHook.replaceSymbol("$ss5print_9separator10terminatoryypd_S2StF", newMethod: myPrintPointer, oldMethod: &oldMethod)
    }
    
    func hookNSLog() {
        typealias NewSwiftNSLog = @convention(thin) (_ format: String, _ args: CVarArg...) -> Void
        func newNSLog(_ format: String, _ args: CVarArg...) {
            
        }
        let nslogSymbol = "$s10Foundation5NSLogyySS_s7CVarArg_pdtF"
        let myNSLog: NewSwiftNSLog = newNSLog
        var oldMethod: UnsafeMutableRawPointer?
        FishHook.replaceSymbol(nslogSymbol, newMethod: unsafeBitCast(myNSLog, to: UnsafeMutableRawPointer.self), oldMethod: &oldMethod)
        
        FishHookChecker.denyFishHook(nslogSymbol)
    }
}

struct UniversalLinkModel: HandyJSON {
    var orderId: String?
    var fromType: String?
}

extension AppDelegate: UNUserNotificationCenterDelegate, PKPushRegistryDelegate {
    func setupUMPush(_ launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        var log = false
        #if DEBUG
        log = true
        #endif
        UMConfigure.setLogEnabled(log)
        UMConfigure.initWithAppkey(kUMAppKey, channel: nil)
        
        UMessage.registerForRemoteNotifications(launchOptions: launchOptions, entity: nil) { (granted, error) in
            if granted {
                
            } else {
                YSGLog("友盟注册失败：\(error?.localizedDescription ?? "")")
            }
        }
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        YSGLog("didRegisterForRemoteNotificationsWithDeviceToken success)")
        
        var deviceId = String()
        if #available(iOS 13.0, *) {
            let bytes = [UInt8](deviceToken)
            bytes.forEach {
                deviceId += String(format:"%02x", $0&0x000000FF)
            }
        } else {
            let device = NSData(data: deviceToken)
            deviceId = device.description
                .replacingOccurrences(of:"<", with:"")
                .replacingOccurrences(of:">", with:"")
                .replacingOccurrences(of:" ", with:"")
        }
        YSGLog("deviceToken：\(deviceId)")
        UserDefaults.saveDeviceToken(deviceId)
        LoginViewModel.bindDeviceTokenForPush(deviceToken: deviceId) { errorMsg in
            if errorMsg != nil {
                HUDTool.showError(message: errorMsg)
            }
        }
    }
    
    // iOS10新增：处理前台收到通知的代理方法
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        YSGLog("前台 userInfo:\(userInfo)")
        guard let trigger = notification.request.trigger,
            trigger.isKind(of: UNPushNotificationTrigger.classForCoder()) else {
            // 应用处于前台时的本地推送接受
            YSGLog("应用处于前台时的本地推送接受")
            return
        }
        
        // 应用处于前台时的远程推送接受
        // 关闭U-Push自带的弹出框
        UMessage.setAutoAlert(false)
        UMessage.didReceiveRemoteNotification(userInfo)
        
        // 当应用处于前台时提示只设置提示音
        completionHandler(.sound)
    }
    
    // iOS10新增：处理后台点击通知的代理方法
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        YSGLog("后台 userInfo: \(userInfo)")
        guard let trigger = response.notification.request.trigger,
            trigger.isKind(of: UNPushNotificationTrigger.classForCoder()) else {
            // 应用处于前台时的本地推送接受
            YSGLog("应用处于前台时的本地推送接受")
            return
        }
        
        UMessage.didReceiveRemoteNotification(userInfo)
        
        NotificationCenter.default.post(name: NotiName.umpushMessage, object: nil, userInfo: userInfo)
    }
    
    // MARK: - PKPushRegistryDelegate
    func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
        YSGLog("type: \(type)")
    }
    
    func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
        YSGLog("enter!")
        guard let str = String(data: pushCredentials.token, encoding: .utf8) else { return }
        let tokenStr = str.replacingOccurrences(of: "<", with: "").replacingOccurrences(of: ">", with: "").replacingOccurrences(of: " ", with: "")
        YSGLog(tokenStr)
    }
}

enum YSGNotiMessageType: String {
    case none = ""
    case chat = "chat"
    case video = "video"
    case cloud = "cloudOutp"
    case prescription = "prescriptionDetail"
    case rejectAdvisory = "orderCancel"
    case endMeeting = "removeVideo"
}

struct YSGNotiMessageModel: HandyJSON {
    var bizType: String = ""
    var diagnoseId: String = ""
    var conferenceID: String = ""
    var conferenceNum: String = ""
    var phoneId: String = ""
    var meetingType: String = ""
    
    var pushType: YSGNotiMessageType { return YSGNotiMessageType(rawValue: bizType) ?? .none }
    
    func chatVideoMsgPush(diagnoseId: String,
                          conferenceId: String,
                          conferenceNum: String,
                          phoneId: String,
                          meetingType: String,
                          finished: @escaping (_ model: ReceiveModel?, _ errorMsg: String?) -> Void)
    {
        let paras = [
            "diagnoseId": diagnoseId,
            "conferenceId": conferenceId,
            "conferenceNum": conferenceNum,
            "phoneId": phoneId,
            "meetingType": meetingType
        ]
        YSGLog("友盟推送获取token: \(paras)")
        HttpTool.shared.request(target: ApiManager.chatVideoMsgPush(paras: paras), success: { (json, code) in
            YSGLog("友盟推送获取token: \(json)")
            switch code {
            case .failure:
                finished(nil, json["message"].description)
            case .success:
                let model = ReceiveModel.deserialize(from: json["data"].description)
                finished(model, nil)
            }
        }) { errorMsg in
            finished(nil, errorMsg)
        }
    }
}

extension AppDelegate: WXApiDelegate {
    func registerWeChat() {
        WXApi.startLog(by: .normal) { logMsg in
            YSGLog("wxapi: \(logMsg)")
        }
        
        WXApi.registerApp(kWeChatAppID, universalLink: "https://health.pmc-wz.com/")
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return WXApi.handleOpen(url, delegate: self)
    }
    
    // MARK: - WXApiDelegate
    // 微信支付回调
    func onResp(_ resp: BaseResp) {
        YSGLog("\(resp.errCode) - \(resp.errStr) - \(resp.type)")
        if resp.isKind(of: WXLaunchMiniProgramResp.classForCoder()) {
            
        } else if resp.isKind(of: PayResp.classForCoder()) {
            if let payResp = resp as? PayResp {
                switch payResp.errCode {
                case WXSuccess.rawValue:
                    YSGLog("支付成功，retcode = \(payResp.errCode)")
                    NotificationCenter.default.post(name: NotiName.wechatPaySuccess, object: nil)
                default:
                    YSGLog("支付失败，retcode = \(payResp.errCode), retstr = \(payResp.errStr)")
                    NotificationCenter.default.post(name: NotiName.wechatPayFailure, object: nil)
                }
            }
        }
    }
}
